var Point2dFactory = {
	fromBean: function( bean ) {
		return bean ? new Point2d( bean.x, bean.y ) : new Point2d( 0, 0 );
	}
	, fromBeans: function( beans ) {
		return Util.each(
			beans
			, function( bean ) { return Point2dFactory.fromBean( bean ); }
		);
	}
};

var Point2d = function( x, y ) {

	this.toString = function() {
		return this.getX() + ' ' + this.getY();
	};

	this.integerDivide = function( p ) {
		this.setX( Math.floor( this.getX() / p.getX() ) );
		this.setY( Math.floor( this.getY() / p.getY() ) );
	};

	this.copy = function( p ) {
		this.setX( p.getX() );
		this.setY( p.getY() );
	};

	this.clone = function() {
		return new Point2d( this.getX(), this.getY() );
	};

	this.tile = function( w, h ) {
		var i = Math.floor( this.getX() / w );
		var j = Math.floor( this.getY() / h );

		this.setX( i * w );
		this.setY( j * h );
	};

	this.toTile = function( w, h ) {
		if ( !h ) h = w;
		var i = Math.floor( this.getX() / w );
		var j = Math.floor( this.getY() / h );
		this.setX( i );
		this.setY( j );
		return this;
	};

	this.distanceSquared = function( p ) {
		return (
			+ ( this.x_ - p.x_ ) * ( this.x_ - p.x_ ) 
			+ ( this.y_ - p.y_ ) * ( this.y_ - p.y_ ) 
		);
	};

	this.distance = function( p ) {
		return Math.sqrt( this.distanceSquared( p ) );
	};

	this.add = function( p ) {
		this.setX( this.getX() + p.getX() );
		this.setY( this.getY() + p.getY() );
	};

	this.setX = function( x ) {
		this.x_ = x;
	};

	this.getX = function() {
		return this.x_;
	};

	this.setY = function( y ) {
		this.y_ = y;
	};

	this.getY = function() {
		return this.y_;
	};

	this.equals = function( that ) {
		return this.x_ == that.x_ && this.y_ == that.y_;
	};

	this.init = function( x, y ) {
		this.setX( x );
		this.setY( y );
	}

	this.init( x, y );
};
